#pragma once
#include "Property.hpp"
#include "DirtyProperty.hpp"
#include "Matrix4x4.hpp"
#include "Vector3.hpp"
#include "Quaternion.hpp"

namespace Typhoon {
	class Camera {
	public:
		Camera();
		~Camera();



		Property<Camera*, float> FieldOfView;
		Property<Camera*, float> Aspect;
		Property<Camera*, float> Near;
		Property<Camera*, float> Far;

		Property<Camera*, Vector3> Position;
		Property<Camera*, Quaternion> Rotation;

		DirtyProperty<Camera*, Matrix4x4> Projection;
		DirtyProperty<Camera*, Matrix4x4> ProjectionInverse;

		DirtyProperty<Camera*, Matrix4x4> World;
		DirtyProperty<Camera*, Matrix4x4> WorldInverse;

		void Begin();
		void End();

		Vector3 ViewToWorld(Vector3 viewPosition);
		Vector3 WorldToView(Vector3 worldPosition);

	private:

		void CalcProjectionMatrix(DirtyProperty<Camera*, Matrix4x4>::EventData& event);
		void CalcProjectionInverseMatrix(DirtyProperty<Camera*, Matrix4x4>::EventData& event);

		void CalcWorldMatrix(DirtyProperty<Camera*, Matrix4x4>::EventData& event);
		void CalcInverseMatrix(DirtyProperty<Camera*, Matrix4x4>::EventData& event);

		
		void ProjectionPropertyChanged(Camera* camera);
		void PropertyChanged(Camera* camera);
		
	};

}